SP26108 TRENDGCD - Trending GCD

i=1nj=1mij(i,j)μ2((i,j))\sum_{i=1}^n\sum_{j=1}^m ij (i,j)\mu^2((i,j))

k=1min(n,m)i=1nj=1m[(i,j)=k]ijkμ2(k)\sum_{k=1}^{\min(n,m)}\sum_{i=1}^n\sum_{j=1}^m [(i,j)=k]ij k\mu^2(k)

k=1min(n,m)k3μ2(k)i=1nkj=1mk[(i,j)=1]ij\sum_{k=1}^{\min(n,m)}k^3\mu^2(k)\sum_{i=1}^{\lfloor \frac{n}{k} \rfloor}\sum_{j=1}^{{\lfloor \frac{m}{k} \rfloor}} [(i,j)=1]ij

k=1min(n,m)k3μ2(k)d=1min(nk,mk)μ(d)d2i=1nkdj=1mkdij\sum_{k=1}^{\min(n,m)}k^3\mu^2(k) \sum_{d=1}^{\min(\lfloor \frac{n}{k} \rfloor,\lfloor \frac{m}{k} \rfloor)}\mu(d)d^2\sum_{i=1}^{\lfloor \frac{n}{kd} \rfloor}\sum_{j=1}^{{\lfloor \frac{m}{kd} \rfloor}} ij

k=1min(n,m)dk=1min(n,m)k3μ2(k)μ(d)d2i=1nkdj=1mkdij\sum_{k=1}^{\min(n,m)}\sum_{dk=1}^{\min(n,m)}k^3\mu^2(k) \mu(d)d^2\sum_{i=1}^{\lfloor \frac{n}{kd} \rfloor}\sum_{j=1}^{{\lfloor \frac{m}{kd} \rfloor}} ij

s(n)=n(n+1)2s(n)=\frac{n(n+1)}{2}

T=1min(n,m)T2s(nT)s(mT)kTkμ2(k)μ(Tk)\sum_{T=1}^{\min(n,m)}T^2 s(\lfloor \frac{n}{T} \rfloor)s(\lfloor \frac{m}{T} \rfloor)\sum_{k|T}k\mu^2(k) \mu(\frac{T}{k})

f(n)=dndμ2(d)μ(nd)f(n)=\sum_{d|n} d\mu^2(d) \mu(\frac{n}{d})

T=1min(n,m)T2f(T)s(nT)s(mT)\sum_{T=1}^{\min(n,m)}T^2 f(T)s(\lfloor \frac{n}{T} \rfloor)s(\lfloor \frac{m}{T} \rfloor)

首先由狄利克雷卷积的性质,f(n)f(n) 是一个积性函数,考虑线性筛。

首先如果 nn 的质因子数量出现 33 次以上,那么 ddnd\frac{n}{d} 一定有一个有平方因子,μ\mu00

那么每个质因子只能出现 11 次或 22 次。

f(p)=1μ2(1)μ(p)+pμ2(p)μ(1)=p1f(p)=1\mu^2(1) \mu(p)+p\mu^2(p)\mu(1)=p-1

f(p2)=1μ2(1)μ(p2)+pμ2(p)μ(p)+p2μ2(p2)μ(1)=pf(p^2)=1\mu^2(1) \mu(p^2)+p\mu^2(p)\mu(p)+p^2\mu^2(p^2)\mu(1)=-p

f(1)=1f(1)=1 ,线筛后乘上 i2i^2 做前缀和就可以整除分块。

#include <cstdio>
#include <iostream>
using namespace std;

const int MAXN = 1e6 , Mod = 1e9 + 7;

int prn , prime[ MAXN + 5 ] , f[ MAXN + 5 ];
bool vis[ MAXN + 5 ];
void sieve( ) {
    f[ 1 ] = 1;
    for( int i = 2 ; i <= MAXN ; i ++ ) {
        if( !vis[ i ] ) { prime[ ++ prn ] = i , f[ i ] = i - 1; }
        for( int j = 1 ; j <= prn && 1ll * i * prime[ j ] <= MAXN ; j ++ ) {
            vis[ i * prime[ j ] ] = 1;
            if( i % prime[ j ] == 0 ) {
                if( ( i / prime[ j ] ) % prime[ j ] ) f[ i * prime[ j ] ] = 1ll * f[ i / prime[ j ] ] * ( Mod - prime[ j ] ) % Mod;
                break;
            }
            f[ i * prime[ j ] ] = 1ll * f[ i ] * f[ prime[ j ] ] % Mod;
        }
    }
    for( int i = 1 ; i <= MAXN ; i ++ ) f[ i ] = ( f[ i - 1 ] + 1ll * f[ i ] * i % Mod * i % Mod ) % Mod;
}
int Sum1( int n ) {
    return 1ll * n * ( n + 1 ) / 2 % Mod;
}
int Solve( int n , int m ) {
    int k = min( n , m ) , Ans = 0;
    for( int l = 1 , r ; l <= k ; l = r + 1 ) {
        r = min( n / ( n / l ) , m / ( m / l ) );
        Ans = ( Ans + 1ll * ( f[ r ] - f[ l - 1 ] + Mod ) % Mod * Sum1( n / l ) % Mod * Sum1( m / l ) % Mod ) % Mod;
    }
    return Ans;
}

int t , n , m;
int main( ) {
    sieve( );
    scanf("%d",&t);
    for( int i = 1 ; i <= t ; i ++ ) {
        scanf("%d %d",&n,&m);
        printf("%d\n", Solve( n , m ) );
    }
    return 0;
}